﻿using System;
using System.Collections.Generic;
using System.Linq;
using PSE.Deployment.SetupBase.Configuration;
using PSE.Deployment.SetupBase.Parameter;
using PSE.Deployment.Engine;
using PSE.Deployment.Engine.CustomEventArgs;
using PSE.Deployment.Engine.Enums;
using PSE.Deployment.Engine.Interfaces;
using PSE.Deployment.Util;
using PSE.Deployment.SetupBase.Parameter.Enums;

namespace PSE.Deployment.SetupBase.Groups
{
    public class SetupGroup : BaseSetupGroup
    {
        public Group Group { get; set; }
        public Parameter.Enums.SetupMode SetupMode { get; set; }

        public SetupGroup(IStepGroup parent, Group group)
            : base(parent)
        {
            this.Id = group.Id;
            this.Description = group.Description;

            Group = group;

            this.ExecutionFinished += new EventHandler<ExecutionFinishedEventArgs>(SetupGroup_ExecutionFinished);
            this.UndoFinished += new EventHandler<UndoFinishedEventArgs>(SetupGroup_UndoFinished);
        }

        public SetupGroup(IStepGroup parent, Group group, Parameter.Enums.SetupMode setupMode)
            : this(parent, group)
        {
            SetupMode = setupMode;

            if (setupMode == Parameter.Enums.SetupMode.Install)
            {
                ExecuteActions(Group.Actions.OrderBy(a => a.Index));
            }
            else if (setupMode == Parameter.Enums.SetupMode.Uninstall)
            {
                ExecuteActions(Group.Actions.OrderByDescending(a => a.Index));
            }
        }

        private void SetupGroup_ExecutionFinished(object sender, ExecutionFinishedEventArgs e)
        {
            if (e.OriginalSource == this)
            {
                //lista todos os grupos com o ID corrente
                IEnumerable<Group> groups = SetupMainFactory.GetInstance().Parameter.SetupConfiguration.SystemInfo.Groups.SelectDeep(g => g.SubGroups).
                    SelectDeep(g => g.Dependencies).Where(g => g.Id == this.Group.Id);

                foreach (Group g in groups)
                {
                    //mudar o estado do grupo
                    g.Install = this.Group.Install;
                    g.Installed = !(SetupMode == PSE.Deployment.SetupBase.Parameter.Enums.SetupMode.Uninstall);
                }
            }
        }

        private void SetupGroup_UndoFinished(object sender, UndoFinishedEventArgs e)
        {
            SetupGroup setupGroup = e.OriginalSource as SetupGroup;

            if (setupGroup != null)
            {
                IEnumerable<Group> groups = SetupMainFactory.GetInstance().Parameter.SetupConfiguration.SystemInfo.Groups.SelectDeep(g => g.SubGroups).
                    SelectDeep(g => g.Dependencies).Where(g => g.Id == setupGroup.Group.Id);

                foreach (Group g in groups)
                {
                    //mudar o estado do grupo
                    g.Install = false;
                    g.Installed = false;
                }
            }
        }

        private void ExecuteActions(IEnumerable<Configuration.ActionBase> actions)
        {
            foreach (Configuration.ActionBase action in actions)
            {
                if (action is Configuration.Actions.Copy)
                {
                    this.Steps.Add(new Steps.Copy(this, this.Group, (Configuration.Actions.Copy)action, SetupMode));
                }

                if (action is Configuration.Actions.CreateShortcut)
                {
                    this.Steps.Add(new Steps.CreateShortcut(this, this.Group, (Configuration.Actions.CreateShortcut)action, SetupMode));
                }

                if (action is Configuration.Actions.InstallAssembly)
                {
                    this.Steps.Add(new Steps.InstallAssembly(this, this.Group, (Configuration.Actions.InstallAssembly)action, SetupMode));
                }

                if (action is Configuration.Actions.InstallCertificate)
                {
                    this.Steps.Add(new Steps.InstallCertificate(this, this.Group, (Configuration.Actions.InstallCertificate)action, SetupMode));
                }

                if (action is Configuration.Actions.InstallMessageQueue)
                {
                    this.Steps.Add(new Steps.InstallMessageQueue(this, this.Group, (Configuration.Actions.InstallMessageQueue)action, SetupMode));
                }

                //if (action is Configuration.Actions.InstallWcfServiceMain)
                //{
                //    //if (SetupMainFactory.GetInstance().Parameter.Prerequisites.IIS7 == PrerequisitesStatus.Ok)
                //    //{
                //        this.Steps.Add(new Steps.InstallWcfServiceMain(this, this.Group, (Configuration.Actions.InstallWcfServiceMain)action, SetupMode));
                //    //}
                //}

                if (action is Configuration.Actions.InstallWcfService)
                {
                    //if (SetupMainFactory.GetInstance().Parameter.Prerequisites.IIS7 == PrerequisitesStatus.NotOk)
                    //{
                        this.Steps.Insert(0, new Steps.StartPackage(this, this.Group, (Configuration.Actions.InstallWcfService)action, SetupMode, false));
                    //}

                    this.Steps.Add(new Steps.InstallWcfService(this, this.Group, (Configuration.Actions.InstallWcfService)action, SetupMode));
                }

                if (action is Configuration.Actions.InstallWindowsService)
                {
                    this.Steps.Add(new Steps.InstallWindowsService(this, this.Group, (Configuration.Actions.InstallWindowsService)action, SetupMode));
                }

                if (action is Configuration.Actions.UpdateWindowsRegistry)
                {
                    this.Steps.Add(new Steps.UpdateWindowsRegistry(this, this.Group, (Configuration.Actions.UpdateWindowsRegistry)action, SetupMode));
                }

                if (action is Configuration.Actions.UpdateConfig)
                {
                    this.Steps.Add(new Steps.UpdateConfig(this, this.Group, (Configuration.Actions.UpdateConfig)action, SetupMode));
                }

                if (action is Configuration.Actions.InstallProcessManagerProduct)
                {
                    this.Steps.Add(new Steps.InstallProcessManagerProduct(this, this.Group, (Configuration.Actions.InstallProcessManagerProduct)action, SetupMode));
                }

                if (action is Configuration.Actions.InstallProcessManagerInstance)
                {
                    this.Steps.Insert(0, new Steps.StartInstance(this, this.Group, (Configuration.Actions.InstallProcessManagerInstance)action, SetupMode, false));

                    this.Steps.Add(new Steps.InstallProcessManagerInstance(this, this.Group, (Configuration.Actions.InstallProcessManagerInstance)action, SetupMode));

                    this.Steps.Add(new Steps.StartInstance(this, this.Group, (Configuration.Actions.InstallProcessManagerInstance)action, SetupMode, true));
                }
            }
        }
    }
}
